package hyl.base.flow.chart;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import hyl.core.MyFun;

/**
 * <p>
 * Description: 节点网络(也叫链路或者节点图)<br>
 * 
 * 
 * 
 * 例如: <br>
 * 节点链路集合:[ "A>B>C>F>H>K>I>L", "B>E>F", "B>D>F", "B>G>K", "B>K", "F>I" ]
 * </p>
 * 
 * @author: 37798
 * @date: 2021年5月31日 下午2:58:45
 * @copyright: 2018 da you zou Inc. All rights reserved.
 */
public class CNodeNet {

	Map<String, INode> 节点集合 = new HashMap<>();

	public INode get节点(String 节点id) {
		return 节点集合.get(节点id);
	}

	public void add节点属性(String 节点id, String 属性) {
		INode nd = 节点集合.get(节点id);
		nd.addAttr(属性);
	}

	public void del节点属性(String 节点id, String 属性) {
		INode nd = 节点集合.get(节点id);
		nd.delAttr(属性);
	}

	public void add链路组(String... 节点链路集合) {
		for (String 节点链路 : 节点链路集合) {
			if (MyFun.isEmpty(节点链路))
				continue;
			String[] 节点集 = 节点链路.split(">");
			INode pnd = null;
			for (String 节点 : 节点集) {
				INode nd = getNode(pnd, 节点);
				pnd = nd;
			}
		}
	}

	public INode getNode(INode 父节点, String 节点id) {
		INode nd = 节点集合.get(节点id);
		if (nd == null) {
			nd = new CNode(节点id);
			节点集合.put(节点id, nd);
		}
		if (父节点 != null) {
			nd.connParent(父节点);
		}
		return nd;
	}
/////////////// 设置工作 //////////////

	/**
	 * 设置节点上的工作行为
	 */
	public void set工人(String 节点id, IWorker work) {
		节点集合.get(节点id).set工人(work);
	}

	public void del工人(String 节点id) {
		节点集合.get(节点id).del工人();
	}

	public IWorker get工人(String 节点id) {
		return 节点集合.get(节点id).get工人();
	}

	public void clear工人() {
		for (Entry<String, INode> item : 节点集合.entrySet()) {
			item.getValue().del工人();
		}
	}

	/**
	 * 
	 * @param 节点集 格式: "A,B,C"
	 * @param 工作
	 */
	public void setWork(String 节点集字符串, IWorker 工作) {
		String[] 节点集 = 节点集字符串.split(",");
		for (String id : 节点集) {
			INode nd = 节点集合.get(id);
			if (nd != null)
				nd.set工人(工作);
		}
	}

	public void setWorks(String 节点集字符串, IWorker[] 工作) {
		String[] 节点集 = 节点集字符串.split(",");
		int i = 0;
		for (String id : 节点集) {
			INode nd = 节点集合.get(id);
			if (nd != null)
				nd.set工人(工作[i++]);
		}
	}

	public void setAllWork(IWorker 工作) {
		for (INode nd : 节点集合.values()) {
			if (nd != null)
				nd.set工人(工作);
		}
	}

	public void setWork(INode[] 节点集, IWorker 工作) {
		for (INode nd : 节点集) {
			if (nd != null)
				nd.set工人(工作);
		}
	}

	public void setWorks(INode[] 节点集, IWorker[] 工作) {
		int i = 0;
		for (INode nd : 节点集) {
			if (nd != null)
				nd.set工人(工作[i++]);
		}
	}
////////////////// 启动线程 加载待处理的数据/////

/////////////// 遍历 //////////////

	public void down(INode pnd, IWorkOrd 工单) {
		new Thread(() -> {
			//MyFun.print(pnd.getId());
			IWorker wk = get工人(pnd.getId());
			if (wk != null) {
				Object 处理结果;
				try {
					//注意 一个工作岗位上的工人不能同时处理两个工单
					synchronized (wk) {
						处理结果 = wk.run(pnd, 工单);
					}
					if (处理结果 == null)
						return;// 为空时停止遍历
				} catch (Exception e) {
					e.printStackTrace();
					return;
				}
			}
			for (INode snode : pnd.getChilds()) {
				down(snode, 工单);
			}
		}).start();
	}

	public void down(String pndid, IWorkOrd 工单) {
		INode pnd = 节点集合.get(pndid);
		down(pnd, 工单);
	}

	public void up(INode pnd, IWorkOrd 工单) {
		new Thread(() -> {
			IWorker wk = get工人(pnd.getId());
			if (wk != null) {
				Object 处理结果;
				try {
					synchronized (wk) {
						处理结果 = wk.run(pnd, 工单);
					}
					if (处理结果 == null)
						return;// 为空时停止遍历
				} catch (Exception e) {
					e.printStackTrace();
					return;// 为空时停止遍历
				}
			}
			for (INode snode : pnd.getParents()) {
				up(snode, 工单);
			}
		}).start();
	}

	public void up(String pndid, IWorkOrd 工单) {
		INode pnd = 节点集合.get(pndid);
		up(pnd, 工单);
	}

}
